package com.cssw.fyzb.busi.service.user;

import com.alibaba.fastjson.JSON;
import com.cssw.fyzb.busi.cache.Cache;
import com.cssw.fyzb.busi.cache.CacheKeys;
import com.cssw.fyzb.busi.cache.Fetcher;
import com.cssw.fyzb.busi.config.ParamConfig;
import com.cssw.fyzb.busi.config.TpsClient;
import com.cssw.fyzb.busi.convert.Converter;
import com.cssw.fyzb.busi.util.NumberUtil;
import com.cssw.fyzb.core.dao.acct.RedPackDao;
import com.cssw.fyzb.core.dao.video.UserVideoDao;
import com.cssw.fyzb.core.eao.user.UserEao;
import com.cssw.fyzb.core.model.vo.user.DistrictTreeNodeVo;
import com.cssw.fyzb.core.model.vo.user.SearchUserVo;
import com.cssw.fyzb.core.model.vo.user.UserForLiveVo;
import com.cssw.fyzb.busi.util.BizUtil;
import com.cssw.fyzb.busi.util.ListToTreeUtil;
import com.cssw.fyzb.core.dao.acct.AcctDao;
import com.cssw.fyzb.core.dao.live.AnchorDao;
import com.cssw.fyzb.core.dao.live.LiveDao;
import com.cssw.fyzb.core.dao.team.UserTreeDao;
import com.cssw.fyzb.core.dao.user.*;
import com.cssw.fyzb.core.mao.live.LiveStatMao;
import com.cssw.fyzb.core.mao.user.UserFollowMao;
import com.cssw.fyzb.core.mao.user.UserMao;
import com.cssw.fyzb.core.model.dodb.*;
import com.cssw.fyzb.core.model.mos.LiveStatMo;
import com.cssw.fyzb.core.model.mos.UserMo;
import com.cssw.fyzb.core.util.AesUtil;
import com.cssw.fyzb.core.util.DateUtil;
import com.cssw.fyzb.core.util.IdUtil;
import com.cssw.fyzb.core.util.StringUtil;
import com.ydn.appserver.Response;
import com.ydn.dbframe.plugin.activerecord.Db;
import com.ydn.dbframe.plugin.activerecord.Page;
import com.ydn.dbframe.plugin.activerecord.Record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.cssw.fyzb.busi.cache.CacheKeys.*;

/**
 * @author Feng Chen
 */
@Service
public class UserServiceImpl implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserSourceDao userSourceDao;

    @Autowired
    private AcctDao acctDao;

    @Autowired
    private UserTreeDao userTreeDao;

    @Autowired
    private UserExtDao userExtDao;

    @Autowired
    private DistrictDao districtDao;

    @Autowired
    private UserMao userMao;

    @Autowired
    private UserRelDao userRelDao;

    @Autowired
    private UserFollowMao userFollowMao;

    @Autowired
    private LiveStatMao liveStatMao;

    @Autowired
    private AnchorDao anchorDao;

    @Autowired
    private LiveDao liveDao;

    @Autowired
    private RedPackDao redPackDao;

    @Autowired
    private TpsClient tpsClient;

    @Autowired
    private ParamConfig paramConfig;

    @Autowired
    private AvatarPendantDefDao avatarPendantDefDao;

    @Autowired
    private FyNoLiangDao fyNoLiangDao;

    @Autowired
    private UserVideoDao userVideoDao;

    @Autowired
    private UserEao userEao;

    @Override
    public Long save(Long supUserId, String mobile, String loginPwd, String tradePwd) {
        final Long[] ids = new Long[1];

        Db.tx(() -> {

            String nickName = "手机用户" + mobile.substring(mobile.length() - 4);
            // 新增用户
            Long userId = userDao.save(supUserId, mobile, loginPwd, tradePwd, 0, paramConfig.getAvatar(), nickName);

            Long fyNo = updateFyNoByRegister(userId);

            // 添加账户
            acctDao.createAcct(userId);
            userExtDao.save(userId);

            // 添加到族谱
            addUserTree(userId, supUserId);
            //用户关系存入
            userTreeDao.cmfAgent(userId, supUserId);

            //同步数据到mongodb
            userMao.save(userId, supUserId, mobile, loginPwd, tradePwd, nickName, paramConfig.getAvatar());

            ids[0] = userId;

            syncToEs(userId, fyNo, nickName, mobile, new Date());

            return true;
        });

        return ids[0];
    }


    private Long updateFyNoByRegister(Long userId){
        FyNoLiang fyNoLiang = fyNoLiangDao.getById(userId);
        //不是靓号
        if (null == fyNoLiang) {
            User fyNoUser = userDao.getByFyNo(userId);
            //用户id的福音号不存在
            if (null == fyNoUser) {
                userDao.updateFyNo(userId, userId, 0);
                return userId;
            } else {
                return randomFyNoByRegister(userId);
            }
        } else {
            return randomFyNoByRegister(userId);
        }
    }

    private Long randomFyNoByRegister(Long userId){
        int loop = 0;
        while (true){
            loop ++;
            if (loop > 100){
                BizUtil.exception("生成FY号失败,请重试！");
                break;
            }
            Long fyNo = Long.valueOf(NumberUtil.getRandomNumber(8));

            FyNoLiang fyNoLiang = fyNoLiangDao.getById(fyNo);
            //不是靓号
            if (null == fyNoLiang) {
                //用户id的福音号不存在
                User fyNoUser = userDao.getByFyNo(fyNo);
                if (null == fyNoUser) {
                    userDao.updateFyNo(userId, fyNo, 0);
                    return fyNo;
                }
            }
        }

        BizUtil.exception("生成FY号失败,请重试！");
        return 0L;
    }

    @Override
    public Long saveUnion(Long supUserId, String mobile, Integer sourceType, String openid, String nickName, String avatar, String loginPwd) {
        final Long[] ids = new Long[1];

        Db.tx(() -> {

            //为空取默认头像
            String newAvatar = avatar;
            if (StringUtil.isEmpty(avatar)) {
                newAvatar = paramConfig.getAvatar();
            }

            String newNickName = nickName;
            if (StringUtil.isEmpty(nickName)) {
                newNickName = "手机号码" + mobile.substring(mobile.length() - 4);
            }

            // 新增用户
            Long userId = userDao.save(supUserId, mobile, loginPwd, null, null, newAvatar, newNickName);

            Long fyNo = updateFyNoByRegister(userId);

            // 新增用户来源
            Long userSourceId = userSourceDao.save(userId, sourceType, openid, "");

            // TODO 添加账户
            acctDao.createAcct(userId);
            userExtDao.save(userId);

            // 添加到族谱
            addUserTree(userId, supUserId);
            //用户关系存入
            userTreeDao.cmfAgent(userId, supUserId);

            //同步数据到mongodb
            userMao.saveUnion(userId, supUserId, mobile, newNickName, newAvatar, loginPwd);

            syncToEs(userId, fyNo, newNickName, mobile, new Date());

            ids[0] = userId;

            return true;
        });

        return ids[0];
    }

    @Override
    public Long saveQQ(Long supUserId, String mobile, String openid, String userName, String nickName, String province, String city, String sex, String avatar) {
        final Long[] ids = new Long[1];

        Db.tx(() -> {
            String newAvatar = avatar;
            if (StringUtil.isEmpty(avatar)) {
                newAvatar = paramConfig.getAvatar();
            }
            String newNickName = nickName;
            if (StringUtil.isEmpty(nickName)) {
                newNickName = "手机号码" + mobile.substring(mobile.length() - 4);
            }

            // 新增用户
            Long userId = userDao.save(supUserId, mobile, null, null, 0, newAvatar, newNickName);

            Long fyNo = updateFyNoByRegister(userId);

            userDao.updateProvince(userId, province);
            userDao.updateCity(userId, city);
            userDao.updateSex(userId, sex);

            // 新增用户来源
            Long userSourceId = userSourceDao.save(userId, 2, null, null);

            // TODO 添加账户
            acctDao.createAcct(userId);
            userExtDao.save(userId);

            // 添加到族谱
            addUserTree(userId, supUserId);
            //用户关系存入
            userTreeDao.cmfAgent(userId, supUserId);

            //同步数据到mongodb
            userMao.saveQQ(userId, supUserId, mobile, userName, newNickName, province, city, sex, newAvatar);

            syncToEs(userId, fyNo, newNickName, mobile, new Date());

            ids[0] = userId;

            return true;
        });

        return ids[0];
    }

    @Override
    public Long saveWechat(Long supUserId, String mobile, String openid, String userName, String nickName, String province, String city, String sex, String avatar) {
        final Long[] ids = new Long[1];

        Db.tx(() -> {
            String newAvatar = avatar;
            if (StringUtil.isEmpty(avatar)) {
                newAvatar = paramConfig.getAvatar();
            }

            String newNickName = nickName;
            if (StringUtil.isEmpty(nickName)) {
                newNickName = "手机号码" + mobile.substring(mobile.length() - 4);
            }
            // 新增用户
            Long userId = userDao.save(supUserId, mobile, null, null, 0, newAvatar, newNickName);

            Long fyNo = updateFyNoByRegister(userId);

            userDao.updateProvince(userId, province);
            userDao.updateCity(userId, city);
            userDao.updateSex(userId, sex);

            // 新增用户来源
            Long userSourceId = userSourceDao.save(userId, 1, null, null);

            // TODO 添加账户
            acctDao.createAcct(userId);
            userExtDao.save(userId);

            // 添加到族谱
            addUserTree(userId, supUserId);
            //用户关系存入
            userTreeDao.cmfAgent(userId, supUserId);

            //同步数据到mongodb
            userMao.saveWechat(userId, supUserId, mobile, userName, newNickName, province, city, sex, newAvatar);

            syncToEs(userId, fyNo, newNickName, mobile, new Date());

            ids[0] = userId;

            return true;
        });

        return ids[0];
    }

    @Override
    public User getById(Long userId) {
        return userDao.getById(userId);
    }

    @Override
    public UserMo findById(Long userId) {
        return userMao.findByUserId(userId);
    }

    @Override
    public UserMo findByMobile(String mobile) {
        return userMao.findByMobile(mobile);
    }

    @Override
    public User getByTradePwd(Long userId, String tradePwd) {
        return userDao.getByTradePwd(userId, tradePwd);
    }

    @Override
    public User getByMobile(String mobile, String pwd) {
        User user = null;
        try {
            user = Cache.get(CacheKeys.mobileKey(mobile), new Fetcher<User>() {
                @Override
                public User fetch() {
                    return userDao.getByMobile(mobile);
                }
            });
        } catch (Exception e) {
            Cache.remove(CacheKeys.mobileKey(mobile));

            user = Cache.get(CacheKeys.mobileKey(mobile), new Fetcher<User>() {
                @Override
                public User fetch() {
                    return userDao.getByMobile(mobile);
                }
            });
        }
        if (null == user) {
            return null;
        }
        if (AesUtil.encode(pwd).equals(user.getLoginPwd())) {
            return user;
        }
        return null;
    }

    @Override
    public User getByMobile(String mobile) {
        User user = null;
        try {
            user = Cache.get(CacheKeys.mobileKey(mobile), new Fetcher<User>() {
                @Override
                public User fetch() {
                    return userDao.getByMobile(mobile);
                }
            });
        } catch (Exception e) {
            Cache.remove(CacheKeys.mobileKey(mobile));

            user = Cache.get(CacheKeys.mobileKey(mobile), new Fetcher<User>() {
                @Override
                public User fetch() {
                    return userDao.getByMobile(mobile);
                }
            });
        }

        return user;
    }

    @Override
    public User getByImsi(String imsi) {
        return userDao.getByImsi(imsi);
    }

    @Override
    public void updateImsi(Long userId, String imsi) {
        Db.tx(() -> {
            userDao.updateImsi(userId, imsi);
            userMao.updateImsi(userId, imsi);
            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));
            return true;
        });
    }

    @Override
    public void updateLoginPwd(Long userId, String mobile, String loginPwd) {
        Db.tx(() -> {
            userDao.updateLoginPwd(userId, loginPwd);
            userMao.updateLoginPwd(userId, mobile, loginPwd);
            Cache.remove(CacheKeys.mobileKey(mobile));
            return true;
        });
    }

    @Override
    public void updateTradePwd(Long userId, String mobile, String tradePwd) {
        Db.tx(() -> {
            userDao.updateTradePwd(userId, tradePwd);
            userMao.updateTradePwd(userId, mobile, tradePwd);
            Cache.remove(CacheKeys.mobileKey(mobile));
            return true;
        });
    }

    @Override
    public void updateAvatar(Long userId, String avatar) {
        Db.tx(() -> {
            userDao.updateAvatar(userId, avatar);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + userId);

            userMao.updateAvatar(userId, avatar);
            return true;
        });
    }

    @Override
    public void updateNickName(Long userId, String nickname) {
        Db.tx(() -> {
            userDao.updateNickName(userId, nickname);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + userId);

            userMao.updateNickName(userId, nickname);

            syncToEs(user.getUserId(), user.getFyNo(), nickname, user.getMobile(), user.getCreateTime());
            return true;
        });
    }

    @Override
    public void updateSex(Long userId, String sex) {
        Db.tx(() -> {
            userDao.updateSex(userId, sex);
            userMao.updateSex(userId, sex);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));
            //删除php用户缓存信息
            Cache.remove("userinfo_" + userId);
            return true;
        });
    }

    @Override
    public void updateStatus(Long userId, String status) {
        Db.tx(() -> {

            userDao.updateStatus(userId, status);
            userMao.updateStatus(userId, status);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));
            //删除php用户缓存信息
            Cache.remove("userinfo_" + userId);
            return true;
        });
    }

    @Override
    public void updateBirthday(Long userId, String birthday) {
        Db.tx(() -> {
            userDao.updateBirthday(userId, birthday);
            userMao.updateBirthday(userId, birthday);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));
            //删除php用户缓存信息
            Cache.remove("userinfo_" + userId);
            return true;
        });
    }

    @Override
    public void updateSign(Long userId, String sign) {
        Db.tx(() -> {
            userDao.updateSign(userId, sign);
            userMao.updateSign(userId, sign);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));
            //删除php用户缓存信息
            Cache.remove("userinfo_" + userId);
            return true;
        });
    }

    private void addUserTree(Long userId, Long supUserId) {
        userTreeDao.save(userId, userId, 0, userId);
        if (supUserId == null) {
            return;
        }

        //固定直插入2级
        //插入上级
        userTreeDao.save(userId, supUserId, 1, supUserId);

        User user = userDao.getById(supUserId);

        if (null == user || user.getSupUserId() == null) {
            return;
        }

        //插入上级的上级
        userTreeDao.save(userId, user.getSupUserId(), 2, supUserId);

//        // TODO 查询上级列表
//        List<UserTree> elems = userTreeDao.getByUserId(supUserId);
//        List<UserTree> userTreeList = new ArrayList<>();
//        for (int i = 0; i < elems.size(); i++) {
//            UserTree elem = null;
//            elem = elems.get(i);
//            if (elem.getLevel() + 1 > 2) {
//                continue;
//            }
//            UserTree userTree = null;
//            userTree = new UserTree();
//            userTree.setUserId(userId);
//            userTree.setSupUserId(elem.getSupUserId());
//            userTree.setLevel(elem.getLevel() + 1);
//            userTreeList.add(userTree);
//        }
//        userTreeDao.batchSave(userTreeList);
    }

    @Override
    public Page<User> listChild(Long userId, String keyword, String isAuth, Integer pageNumber, Integer pageSize) {

        Map param = new HashMap<>();
        param.put("supUserId", userId);
        param.put("isReal", isAuth);
        param.put("keyword", keyword);
        return userDao.listUserChildByCond(param, pageNumber, pageSize);
    }

    @Override
    public Page<User> pageUserFans(Long userId, Integer pageNumber, Integer pageSize) {
        Map param = new HashMap<>();
        param.put("userId", userId);
        return userDao.pageUserFans(param, pageNumber, pageSize);
    }

    @Override
    public Page<User> pageUserFollow(Long userId, Integer pageNumber, Integer pageSize) {
        Map param = new HashMap<>();
        param.put("userId", userId);
        return userDao.pageUserFollow(param, pageNumber, pageSize);
    }

    @Override
    public Page<User> pageUserFriend(Long userId, Integer pageNumber, Integer pageSize) {
        Map param = new HashMap<>();
        param.put("userId", userId);
        return userDao.pageUserFriend(param, pageNumber, pageSize);
    }

    @Override
    public void updateFaceAuth(User user, String status) {
        Db.tx(() -> {
            userDao.updateFaceAuth(user, status);
            userMao.updateFaceAuth(user.getUserId(), status);

            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + user.getUserId());
            return true;
        });
    }

    @Override
    public void updateFace(Long userId, String status) {
        Db.tx(() -> {
            userDao.updateFace(userId, status);
            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));
            //删除php用户缓存信息
            Cache.remove("userinfo_" + user.getUserId());
            return true;
        });
    }

    @Override
    public List<DistrictTreeNodeVo> getDistrictTree() {
        List<District> all = districtDao.list();
        List<DistrictTreeNodeVo> treeNodeVo = ListToTreeUtil.getTree(all);
        return treeNodeVo;
    }

    @Override
    public void follow(Long userId, Long followUserId) {
        UserRel userRel = userRelDao.getByUIdAndRId(userId, followUserId);
        if (null != userRel) {
            return;
        }
        Db.tx(() -> {
            UserRel followUserRel = userRelDao.getByUIdAndRId(followUserId, userId);
            if (null != followUserRel) {
                userRelDao.updateRelType(followUserRel.getId(), UserRel.REL_TYPE_FRIEND);
                userRelDao.save(userId, followUserId, UserRel.REL_TYPE_FRIEND);
                //增加数据库统计数据
                userExtDao.incFriendsNum(userId, 1);
                userExtDao.incFriendsNum(followUserId, 1);
            } else {
                userRelDao.save(userId, followUserId, UserRel.REL_TYPE_FOLLOW);
            }

            //关注用户增加关注数，被关注用户增加粉丝数
            userMao.incFollows(userId);
            userMao.incFans(followUserId);

            //增加数据库统计数据
            userExtDao.incFansNum(followUserId, 1);

            userFollowMao.addFollow(userId, followUserId);
            return true;
        });
    }

    @Override
    public void cancelFollow(Long userId, Long followUserId) {
        UserRel userRel = userRelDao.getByUIdAndRId(userId, followUserId);
        if (null == userRel) {
            return;
        }

        Db.tx(() -> {
            if (userRel.getRelType() == UserRel.REL_TYPE_FRIEND) {
                userRelDao.updateRelType(followUserId, userId, UserRel.REL_TYPE_FOLLOW);
                //增加数据库统计数据
                userExtDao.decFriendsNum(userId, 1);
                userExtDao.decFriendsNum(followUserId, 1);
            }
            userRelDao.delete(userRel.getId());
            userFollowMao.removeFollow(userId, followUserId);

            //关注用户增加关注数，被关注用户增加粉丝数
            userMao.decFollows(userId);
            userMao.decFans(followUserId);
            //增加数据库统计数据
            userExtDao.decFansNum(followUserId, 1);

            return true;
        });
    }


    @Override
    public void saveSendAuthFaceSucc(String orderNo, String nonce, String respCode, String respMsg, Long
            userId, String userName, String idNo) {
        userDao.saveTecentAuthFaceSend(orderNo, nonce, userId, TecentAuthFaceSend.STATUS_SUCC, respCode, respMsg, userName, idNo);
    }

    @Override
    public void saveSendAuthFaceFail(String orderNo, String nonce, String respCode, String respMsg, Long
            userId, String userName, String idNo) {
        userDao.saveTecentAuthFaceSend(orderNo, nonce, userId, TecentAuthFaceSend.STATUS_FAIL, respCode, respMsg, userName, idNo);
    }

    @Override
    public void saveQueryAuthFaceSucc(String orderNo, String nonce, String respCode, String respMsg, Long
            userId, String userName, String idNo) {
        userDao.saveTecentAuthFaceQuery(orderNo, nonce, userId, TecentAuthFaceQuery.STATUS_SUCC, respCode, respMsg, userName, idNo);
    }

    @Override
    public void saveQueryAuthFaceFail(String orderNo, String nonce, String respCode, String respMsg, Long
            userId, String userName, String idNo) {
        userDao.saveTecentAuthFaceQuery(orderNo, nonce, userId, TecentAuthFaceQuery.STATUS_FAIL, respCode, respMsg, userName, idNo);
    }

    @Override
    public TecentAuthFaceSend getTecentAuthFaceSend(Long userId, String orderNo) {
        return userDao.getTecentAuthFaceSend(userId, orderNo);
    }

    @Override
    public void saveAuthInfo(Long userId, String userName, String province, String city, String district, String
            idCard) {
        Db.tx(() -> {
            userDao.saveAuthInfo(userId, userName, province, city, district, idCard);
            userMao.updateAuthInfo(userId, userName, province, city, district, idCard);

            User user = userDao.getById(userId);
            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + user.getUserId());
            return true;
        });
    }

    @Override
    public boolean isFollow(Long userId, Long relUserId) {
        return userFollowMao.exists(userId, relUserId);
    }

    @Override
    public Page<SearchUserVo> searchUser(Long userId, String key, Integer pageNumber, Integer pageSize) {
        Map<String, Object> param = new HashMap<>();
        param.put("key", key);

        Page<User> page = userDao.searchUser(param, pageNumber, pageSize);

        List<SearchUserVo> list = ((Converter<List<User>, List<SearchUserVo>>) users -> {
            List<SearchUserVo> vos = new ArrayList<>();

            users.forEach((v) -> {
                SearchUserVo vo = new SearchUserVo();

                vo.setUserId(v.getUserId());
                vo.setNickName(v.getNickName());
                vo.setAvatar(v.getAvatar());
                vo.setFollow(userFollowMao.exists(userId, v.getUserId()) ? "1" : "0");

                vos.add(vo);
            });
            return vos;
        }).convert(page.getList());

        return new Page<>(list, pageNumber, pageSize, page.getTotalPage(), page.getTotalRow());
    }

    @Override
    public UserForLiveVo getUserForLive(Long userId, Long liveId, Long liveUserId) {
        UserForLiveVo userForLiveVo = new UserForLiveVo();
        LiveStatMo liveStatMo = liveStatMao.findByLiveId(liveId);

        if (userId.toString().equals(liveStatMo.getUserId().toString())) {
            userForLiveVo.setType("1");
        } else if (isAnchorManage(liveStatMo.getAnchorId(), userId)) {
            userForLiveVo.setType("2");
        } else {
            userForLiveVo.setType("3");
        }

        UserMo liveUserMo = userMao.findByUserId(liveUserId);
        userForLiveVo.setUserId(liveUserId);
        userForLiveVo.setAvatar(liveUserMo.getAvatar());
        userForLiveVo.setNickName(liveUserMo.getNickName());
        userForLiveVo.setSign(liveUserMo.getSign());
        userForLiveVo.setSex(liveUserMo.getSex());
        userForLiveVo.setFollow(userFollowMao.exists(userId, liveUserId) ? "1" : "0");
        userForLiveVo.setBlack(isAnchorBlack(liveStatMo.getAnchorId(), liveUserId) ? "1" : "0");
        userForLiveVo.setAdmin(isAnchorManage(liveStatMo.getAnchorId(), liveUserId) ? "1" : "0");
        userForLiveVo.setMute(isLiveMute(liveId, liveUserId) ? "1" : "0");
        userForLiveVo.setFans(liveUserMo.getFans());
        userForLiveVo.setFollows(liveUserMo.getFollows());

        return userForLiveVo;
    }


    private boolean isAnchorBlack(Long anchorId, Long userId) {
        List<CmfAnchorBlacklist> list = getAnchorBlackByAnchorId(anchorId);

        if (null == list) {
            return false;
        }
        for (CmfAnchorBlacklist blacklist : list) {
            if (blacklist.getUserId().toString().equals(userId.toString())) {
                return true;
            }
        }

        return false;
    }

    private List<CmfAnchorBlacklist> getAnchorBlackByAnchorId(Long anchorId) {
        String cacheStr = Cache.get(anchorBlackKey(anchorId));

        List<CmfAnchorBlacklist> blacklists = null;
        if (StringUtil.isEmpty(cacheStr)) {
            blacklists = anchorDao.listAnchorBlacklist(anchorId);

            if (null == blacklists) {
                blacklists = new ArrayList<>();
            }
            Cache.put(anchorBlackKey(anchorId), JSON.toJSONString(blacklists));
        } else {
            blacklists = JSON.parseArray(cacheStr, CmfAnchorBlacklist.class);
        }

        return blacklists;
    }

    private boolean isAnchorManage(Long anchorId, Long userId) {
        List<CmfAnchorManage> list = getAnchorManageByAnchorId(anchorId);

        if (null == list) {
            return false;
        }
        for (CmfAnchorManage cmfAnchorManage : list) {
            if (cmfAnchorManage.getUserId().toString().equals(userId.toString())) {
                return true;
            }
        }

        return false;
    }

    private List<CmfAnchorManage> getAnchorManageByAnchorId(Long anchorId) {
        String cacheStr = Cache.get(anchorManageKey(anchorId));

        List<CmfAnchorManage> cmfAnchorManages = null;
        if (StringUtil.isEmpty(cacheStr)) {
            cmfAnchorManages = anchorDao.listAnchorManage(anchorId);

            if (null == cmfAnchorManages) {
                cmfAnchorManages = new ArrayList<>();
            }
            Cache.put(anchorManageKey(anchorId), JSON.toJSONString(cmfAnchorManages));
        } else {
            cmfAnchorManages = JSON.parseArray(cacheStr, CmfAnchorManage.class);
        }

        return cmfAnchorManages;
    }

    private boolean isLiveMute(Long liveId, Long userId) {
        List<CmfLiveMute> list = getLiveMuteByLiveId(liveId);

        if (null == list) {
            return false;
        }
        for (CmfLiveMute cmfLiveMute : list) {
            if (cmfLiveMute.getUserId().toString().equals(userId.toString())) {
                return true;
            }
        }

        return false;
    }

    private List<CmfLiveMute> getLiveMuteByLiveId(Long liveId) {
        String cacheStr = Cache.get(liveMuteKey(liveId));

        List<CmfLiveMute> cmfLiveMutes = null;
        if (StringUtil.isEmpty(cacheStr)) {
            cmfLiveMutes = liveDao.listLiveMute(liveId);

            if (null == cmfLiveMutes) {
                cmfLiveMutes = new ArrayList<>();
            }
            Cache.put(anchorManageKey(liveId), JSON.toJSONString(cmfLiveMutes));
        } else {
            cmfLiveMutes = JSON.parseArray(cacheStr, CmfLiveMute.class);
        }

        return cmfLiveMutes;
    }

    @Override
    public User getAuthUserById(String idCard) {
        return userDao.getAuthUserById(idCard);
    }

    @Override
    public void saveCmfToken(Long userId, String token) {
        userDao.saveCmfToken(userId, token);
    }

    public void saveCmfUserAuth(String userName, String msg, Boolean status, Integer userId) {
        userDao.saveCmfUserAuth(userName, msg, status, userId);
    }

    @Override
    public CmfUserToken getCmfTokenByUserId(Long userId) {
        return userDao.getCmfTokenByUserId(userId);
    }

    @Override
    public void updateCmfToken(CmfUserToken userToken) {
        userDao.updateCmfToken(userToken);
    }

    @Override
    public void updateCmfUser(CmfUser cmfUser) {
        userDao.updateCmfUser(cmfUser);
    }

    @Override
    public void syncUserToMongo(Long userId, String type) {

        if ("all".equals(type)) {
            int pageNum = 1;
            int pageSize = 100;

            while (true) {
                Page<User> pages = userDao.page(pageNum, pageSize);
                if (pages.getList() == null || pages.getList().size() <= 0) {
                    break;
                }
                pageNum++;

                for (User user : pages.getList()) {
                    syncToMongo(user);
                }
            }
        } else {
            User user = userDao.getById(userId);
            syncToMongo(user);
        }
    }

    @Override
    public void syncUserToEs(Long userId, String type) {
        if ("all".equals(type)) {
            int pageNum = 1;
            int pageSize = 100;

            while (true) {
                Page<User> pages = userDao.page(pageNum, pageSize);
                if (pages.getList() == null || pages.getList().size() <= 0) {
                    break;
                }
                pageNum++;

                for (User user : pages.getList()) {
                    syncToEs(user);
                }
            }
        } else {
            User user = userDao.getById(userId);
            syncToEs(user);
        }
    }


    private void syncToEs(User user) {
        if (null == user) {
            return;
        }

        syncToEs(user.getUserId(), user.getFyNo(), user.getNickName(), user.getMobile(), user.getCreateTime());

    }

    private void syncToEs(Long userId, Long fyNo, String nickName, String mobile, Date createTime) {
        try {
            userEao.save(userId, fyNo, nickName, mobile,createTime);
        } catch (Exception e){
            logger.error("", e);
        }
    }

    private void syncToMongo(User user) {
        if (null == user) {
            return;
        }
        UserMo userMo = userMao.findByUserId(user.getUserId());

        UserMo updateMo = convertToUserMo(user);
        if (null != userMo) {
            updateMo.setFans(userMo.getFans());
            updateMo.setFollows(userMo.getFollows());
            updateMo.setAnchor(userMo.getAnchor());
            updateMo.setLive(userMo.getLive());
            userMao.update(updateMo);
        } else {
            userMao.save(updateMo);
        }

    }

    private UserMo convertToUserMo(User user) {
        UserMo userMo = new UserMo();
        userMo.setUserId(user.getUserId());
        userMo.setMobile(user.getMobile());
        userMo.setSupUserId(user.getSupUserId());
        userMo.setUserName(user.getUserName());
        userMo.setNickName(user.getNickName());
        userMo.setProvince(user.getProvince());
        userMo.setCity(user.getCity());
        userMo.setDistrict(user.getDistrict());
        userMo.setStatus(user.getStatus());
        userMo.setSex(user.getSex());
        userMo.setIdCard(user.getIdCard());
        userMo.setBirthDay(user.getBirthday());
        userMo.setLoginPwd(user.getLoginPwd());
        userMo.setTradePwd(user.getTradePwd());
        userMo.setFaceAuth(user.getFaceAuth());
        userMo.setUserLevel(user.getUserLevel());
        userMo.setTeamLevel(user.getTeamLevel());
        userMo.setCreateTime(user.getCreateTime());
        userMo.setSign(user.getSign());
        userMo.setAvatar(user.getAvatar());
        userMo.setAnchor("0");
        userMo.setLive("0");
        userMo.setFollows(0);
        userMo.setFans(0);
        return userMo;
    }

    @Override
    public User getIdCard(String idCard) {
        return userDao.getIdCard(idCard);
    }

    public Integer hairRedPack(Long userId) {
        CmfUserLive cmfUserLive = liveDao.getCmfUserLive(userId);
        CmfLiveRedPack cmfLiveRedPack = redPackDao.getLiveRed(userId);
        if (cmfLiveRedPack != null && cmfUserLive != null && cmfUserLive.getStarttime() < cmfLiveRedPack.getSendTime().getTime() / 1000) {
            //红包时间大于开播时间 当前直播有发红包
            if (cmfLiveRedPack.getRestNum() != 0) {
                //还有剩余红包
                return 1;
            }
            return 0;
        }
        return 0;
    }

    @Override
    public void saveAuthRecord(Long userId, String userName, String idCard, String province, String city, String district) {
        try {
            userDao.saveAuthRecord(userId, userName, idCard, province, city, district);
        } catch (Exception e){
            logger.error("", e);
        }
    }

    @Override
    public List<AvatarPendantDef> listAvatarPendantDef() {
        return avatarPendantDefDao.listValid();
    }

    @Override
    public void updatePendantUrl(Long userId, Long pendantId) {
        User user = userDao.getById(userId);
        if (!user.isVip()){
            BizUtil.exception("您不是vip会员");
        }

        Db.tx(() -> {
            AvatarPendantDef avatarPendantDef = avatarPendantDefDao.getById(pendantId);
            if (null == avatarPendantDef){
                BizUtil.exception("头像挂件不存在");
            }

            userDao.updatePendantUrl(userId, avatarPendantDef.getPendantUrl());

            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + user.getUserId());
            return true;
        });
    }

    @Override
    public void updateFyNo(Long userId, Long fyNo) {
        if (String.valueOf(fyNo).length() != 8){
            BizUtil.exception("FY号必须是8位");
        }

        User user = userDao.getById(userId);
        if (!user.isVip()){
            BizUtil.exception("您不是vip会员");
        }

        if (fyNo.toString().equals(user.getFyNo())){
            BizUtil.exception("您未修改FY号");
        }

        Db.tx(() -> {
            int fyNoNum = 0;
            if (null == user.getFyNoNum()) {
                fyNoNum = 0;
            } else {
                fyNoNum = user.getFyNoNum();
            }

            //判断是否修改过
            if (fyNoNum > 0){
                BizUtil.exception("您已修改过FY号，不可变更，如有疑问，请联系客服");
            }

            //靓号被他人占用
            User fyUser = userDao.getByFyNo(fyNo);
            if (null != fyUser){
                BizUtil.exception("该FY号已被他人选择");
            }

            //靓号不允许配置
            FyNoLiang fyNoLiang = fyNoLiangDao.getById(fyNo);
            if (null != fyNoLiang){
                BizUtil.exception("该FY号已被他人选择");
            }

            fyNoNum++;

            userDao.updateFyNo(userId, fyNo, fyNoNum);

            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + user.getUserId());


            syncToEs(user.getUserId(), fyNo, user.getNickName(), user.getMobile(), user.getCreateTime());
            return true;
        });
    }


    @Override
    public void resetPendantUrl(Long userId) {
        User user = userDao.getById(userId);
        if (!user.isVip()){
            BizUtil.exception("您不是vip会员");
        }

        Db.tx(() -> {
            userDao.updatePendantUrl(userId, null);

            Cache.remove(CacheKeys.mobileKey(user.getMobile()));

            //删除php用户缓存信息
            Cache.remove("userinfo_" + user.getUserId());
            return true;
        });
    }

    @Override
    public void syncLikesToMongo(Long userId, String type) {
        if ("all".equals(type)) {
            int pageNum = 1;
            int pageSize = 100;

            while (true) {
                Page<Record> pages = userVideoDao.pageByCountLikes(pageNum, pageSize);
                if (pages.getList() == null || pages.getList().size() <= 0) {
                    break;
                }
                pageNum++;

                for (Record record : pages.getList()) {
                    userMao.updateLikes(record.getLong("uid"), record.getInt("likes"));
                }
            }
        } else {
            Integer countLikes = userVideoDao.countLikes(userId);
            userMao.updateLikes(userId, countLikes);
        }
    }
}
